
/**
 * Loading Gadget URL.
 * @type {string}
 * @const.
 */
LOADING_GADGET = 'http://fifa-bot.appspot.com/static/loading.xml';

/**
 * List of teams.
 * @type {Object}
 * @const
 */
var TEAMS = {
  '43843': {name: 'Algeria', id: 'ALG', isoCode: 'DZA'},
  '43922': {name: 'Argentina', id: 'ARG', isoCode: 'ARG'},
  '43976': {name: 'Australia', id: 'AUS', isoCode: 'AUS'},
  '43924': {name: 'Brazil', id: 'BRA', isoCode: 'BRA'},
  '43849': {name: 'Cameroon', id: 'CMR', isoCode: 'CMR'},
  '43925': {name: 'Chile', id: 'CHI', isoCode: 'CHL'},
  '43854': {name: 'Côte d\'Ivoire', id: 'CIV', isoCode: 'CIV'},
  '43941': {name: 'Denmark', id: 'DEN', isoCode: 'DNK'},
  '43942': {name: 'England', id: 'ENG', isoCode: 'GBR'},
  '43946': {name: 'France', id: 'FRA', isoCode: 'FRA'},
  '43948': {name: 'Germany', id: 'GER', isoCode: 'DEU'},
  '43860': {name: 'Ghana', id: 'GHA', isoCode: 'GHA'},
  '43949': {name: 'Greece', id: 'GRE', isoCode: 'GRC'},
  '43909': {name: 'Honduras', id: 'HON', isoCode: 'HND'},
  '43954': {name: 'Italy', id: 'ITA', isoCode: 'ITA'},
  '43819': {name: 'Japan', id: 'JPN', isoCode: 'JPN'},
  '43821': {name: 'Korea DPR', id: 'PRK', isoCode: 'PRK'},
  '43822': {name: 'Korea Republic', id: 'KOR', isoCode: 'KOR'},
  '43911': {name: 'mexico', id: 'MEX', isoCode: 'MEX'},
  '43960': {name: 'netherlands', id: 'NED', isoCode: 'NLD'},
  '43978': {name: 'New Zealand', id: 'NZL', isoCode: 'NZL'},
  '43876': {name: 'Nigeria', id: 'NGA', isoCode: 'NGA'},
  '43928': {name: 'Paraguay', id: 'PAR', isoCode: 'PRY'},
  '43963': {name: 'Portugal', id: 'POR', isoCode: 'PRT'},
  '1902465': {name: 'Serbia', id: 'SRB', isoCode: 'SRB'},
  '44002': {name: 'Slovakia', id: 'SVK', isoCode: 'SVK'},
  '43968': {name: 'Slovenia', id: 'SVN', isoCode: 'SVN'},
  '43883': {name: 'South Africa', id: 'RSA', isoCode: 'ZAF'},
  '43969': {name: 'Spain', id: 'ESP', isoCode: 'ESP'},
  '43971': {name: 'Switzerland', id: 'SUI', isoCode: 'CHE'},
  '43930': {name: 'Uruguay', id: 'URU', isoCode: 'URY'},
  '43921': {name: 'USA', id: 'USA', isoCode: 'USA'}
};

var MESSAGES = {
  // Strings for all the Teams in the tournament.
  'ALG': 'Algeria',
  'CMR': 'Cameroon',
  'CHI': 'Chile',
  'CIV': 'Côte d\'Ivoire',
  'DEN': 'Denmark',
  'GHA': 'Ghana',
  'GRE': 'Greece',
  'HON': 'Honduras',
  'PRK': 'Korea DPR',
  'KOR': 'Korea Republic',
  'NZL': 'New Zealand',
  'NGA': 'Nigeria',
  'PAR': 'Paraguay',
  'SRB': 'Serbia',
  'SVK': 'Slovakia',
  'SVN': 'Slovenia',
  'RSA': 'South Africa',
  'ESP': 'Spain',
  'SUI': 'Switzerland',
  'USA': 'USA',
  'URU': 'Uruguay',

  // Strings of all the venues and cities of the tournament.
  'VC_5007758': 'Peter Mokaba Stadium, Polokwane',
  'VC_5007765': 'Loftus Versfeld Stadium, Pretoria',
  'VC_5007763': 'Mbombela Stadium, Nelspruit',
  'VC_5007767': 'Royal Bafokeng Stadium, Rustenburg',
  'VC_5007759': 'Soccer City, Johannesburg',
  'VC_5006468': 'Ellis Park, Johannesburg',
  'VC_5002942': 'Free State Stadium, Bloemfontein',
  'VC_5011924': 'Green Point Stadium, Cape Town',
  'VC_5018127': 'Moses Mabhida Stadium, Durban',
  'VC_5007768': 'Nelson Mandela Bay Stadium, Port Elizabeth',

  // Strings of all the cities of the tournament.
  'C_5007758': 'Polokwane',
  'C_5007765': 'Pretoria',
  'C_5007763': 'Nelspruit',
  'C_5007767': 'Rustenburg',
  'C_5007759': 'Johannesburg',
  'C_5006468': 'Johannesburg',
  'C_5002942': 'Bloemfontein',
  'C_5011924': 'Cape Town',
  'C_5018127': 'Durban',
  'C_5007768': 'Port Elizabeth',

  // Strings of all the venues of the tournament.
  'V_5007758': 'Peter Mokaba Stadium',
  'V_5007765': 'Loftus Versfeld Stadium',
  'V_5007763': 'Mbombela Stadium',
  'V_5007767': 'Royal Bafokeng Stadium',
  'V_5007759': 'Soccer City',
  'V_5006468': 'Ellis Park',
  'V_5002942': 'Free State Stadium',
  'V_5011924': 'Green Point Stadium',
  'V_5018127': 'Moses Mabhida Stadium',
  'V_5007768': 'Nelson Mandela Bay Stadium',

  // Strings for the status of the matches played.
  'MS_0': 'Played',
  'MS_1': 'To Be Played',
  'MS_2': 'Undefined',
  'MS_3': 'Playing',
  'MS_4': 'Postponed',
  'MS_5': 'Suspended',
  'MS_6': 'Abandoned',

  'M_0': 'January',
  'M_1': 'February',
  'M_2': 'March',
  'M_3': 'April',
  'M_4': 'May',
  'M_5': 'June',
  'M_6': 'July',
  'M_7': 'August',
  'M_8': 'September',
  'M_9': 'October',
  'M_10': 'November',
  'M_11': 'December',

  // Common strings.
  'match': 'Match %NUMBER%',
  'date_format': '%mmmm% %d%, %yyyy%'
};

/**
 * Domain Url for images of flags of the nations.
 * @type {string}
 * @const
 */
var FLAG_URL = 'http://www.google.com/images/flags/small/';

/**
 * Url to fetch standings from FIFA.com.
 * @type {string}
 * @const
 */
var STANDINGS_URL =
    'http://fifa-bot.appspot.com/makeRequest?url=' +
    'http://en.syndication.fifa.com/standings/worldcup/list_overview.xml';

/**
 * Url to fetch schedule from FIFA.com.
 * @type {string}
 * @const
 */
var SCHEDULE_URL =
    'http://fifa-bot.appspot.com/makeRequest?url=' +
    'http://en.syndication.fifa.com/matches/worldcup/list_overview.xml';

var events = [];

/**
 * Parsing world cup events data.
 * @param {string} response The response from the server.
 * @return {Array} Array of event objects.
 */
function parseWorldCupEventsData(response) {
  events = [];
  //var responseXml = response.responseXML;
  var matches = response.getElementsByTagName('Match');
  for (var i = 0, match; match = matches[i]; i++) {
    var obj = {};
    obj.matchCode = getAttributeValue(match, 'code');
    var numOfChildNodes = match.childNodes.length;
    for (var j = 0; j < numOfChildNodes; j++) {
      var childElement = match.childNodes.item(j);
      if (childElement.nodeType == 1) {
        switch (childElement.nodeName) {
          case 'Round':
            obj.round = getNodeValue(childElement);
            break;
          case 'UTCDateTime':
            obj.date = getMatchDateObj(getNodeValue(childElement));
            break;
          case 'Group':
            obj.group = getNodeValue(childElement);
            obj.groupCode = getAttributeValue(childElement, 'code');
            break;
          case 'MatchNumber':
            obj.matchNumber = getNodeValue(childElement);
            break;
          case 'MatchDay':
            obj.matchDay = getNodeValue(childElement);
            break;
          case 'Status':
            obj.status = getAttributeValue(childElement, 'code');
            break;
          case 'OfficialSiteLink':
            obj.link = getNodeValue(childElement) + '?cid=google_onebox';
            break;
          case 'Attendance':
            obj.Attendance = getNodeValue(childElement) || '-';
            break;
          case 'Team':
            var home = getAttributeValue(childElement, 'type') == 'H' ? 1 : 2;
            obj['team' + home + 'Code'] =
              getAttributeValue(childElement, 'code');
            for (var k = 0; k < childElement.childNodes.length; k++) {
              var element = childElement.childNodes.item(k);
              if (element.nodeType == 1) {
                switch (element.nodeName) {
                  case 'FullName':
                    obj['team' + home] = getNodeValue(element);
                    break;
                  case 'ShortName':
                    obj['team' + home + 'id'] = getNodeValue(element);
                   break;
                }
              }
            }
            break;
          case 'Venue':
            for (var l = 0; l < childElement.childNodes.length; l++) {
              var element = childElement.childNodes.item(l);
              if (element.nodeType == 1) {
                switch (element.nodeName) {
                  case 'Stadium':
                    obj.venueCode = getAttributeValue(element, 'code')
                  break;
                }
              }
            }
        }
      }
    }
    events.push(obj);
  }
  console.log('Events: ', events);
  return events;
};

/**
 * Gets the latest news of fifa world cup.
 * @param {Object} item Object of the current event.
 * @return {string} Match result/timings/status based on the status.
 */
function getMatchResult(item) {
  // If the event is "played" show final score.
  if (item.status == 0) {
    return item.finalScore;
  } else if (item.status == 1) {
     // If match status is "To Be Played" show the time when
     // match will be played.
    return getTime(item.date);
  } else if (item.status == 3) {
    // If match status is "Playing" show the Live score.
    return item.liveScore;
  } else {
    // Show the status info. It can be Postponed, Suspended, Abandoned.
    return MESSAGES['MS_' + item.status];
  }
};

/**
 * Generates html of the match's fixture of the current league
 * and returns the string.
 * @param {Object} item Object of the current event.
 * @return {string} Html of the current event.
 */
function createMatchSchedule(item) {
  var team1 = item.team1, team2 = item.team2;
  var flag1 = '', flag2 = '';
  if (item.team1Code) {
    team1 = TEAMS[item.team1Code].name;
    flag1 = '<span title="' + TEAMS[item.team1Code].name + '"><img src="' +
            FLAG_URL + TEAMS[item.team1Code].isoCode + '.gif"></span>';
  }
  if (item.team2Code) {
    team2 = TEAMS[item.team2Code].name;
    flag2 = '<span title="' + TEAMS[item.team2Code].name +
            '"><img src="' + FLAG_URL + TEAMS[item.team2Code].isoCode +
            '.gif"></span>';
  }
  var matchNumber = item.matchNumber;
  var html = [
    '<form target="_blank" id="wave-this-', matchNumber,
    '" action="https://wave.google.com/wave/wavethis" method="GET">',
    '<input type="hidden" name="t" value="Wave by FIFA WORLD CUP Extension" />',
    '<input type="hidden" name="u" id="url-reference-', matchNumber,
    '" value="http://fifa-bot.appspot.com/getMatch?match=', matchNumber,
    '&team1=', team1, '&team2=', team2, '" />',
    '<input type="hidden" name="c" value="', getWaveContent(matchNumber),'" />',
    '<input type="hidden" name="r" value="fifa-bot@appspot.com" />',
    '<input type="hidden" name="g" value="', LOADING_GADGET, '" />',
    '<table width="100%"><tr>',
    '<td class="match-table-date dot-line-bottom" width="25%" align="left">'
  ];
  var venue = MESSAGES['V_' + item.venueCode].split(',')[0];
  html.push(getTime(item.date) + ', ', getDateInLocaleFormat(item.date),
      '</td><td class="match-table-head dot-line-bottom" ',
      'colspan="2" align="right">',
      '<a href="javascript:getVenues(\'', item.venueCode, '\')">',
      venue, '</a></td>',
      '<td rowspan="3" width="20%" class="wavethis-button"><a href="javascript',
      ':waveThis(', item.matchNumber, ', \'betting\')">Betting</a></td>',
      '<td rowspan="3" width="20%" class="wavethis-button"><a href="javascript',
      ':waveThis(', item.matchNumber, ', \'party\')">Party planning</a></td></tr>',
      '<tr><td width="25%" class="match-table-home-score" ',
      'valign="bottom">', flag1, '&nbsp;&nbsp;<span>', team1,
      '</span></td>',
      '<td width="*" class="match-table-home-team" ',
      'valign="bottom"><span><a class="fifa-score" href="',
      item.link, '" target="_blank">', getMatchResult(item),
      '</a></span></td>',
      '<td width="25%" class="match-table-away-score" ',
      'valign="bottom"><div><span>', team2,
      '</span>&nbsp;&nbsp;', flag2, '</div></td></tr>',
      '<tr><td colspan="3" align="center" class="match-number dot-line-bottom"',
      ' valign="top">',
      MESSAGES['match'].replace('%NUMBER%', item.matchNumber),
      '</td></tr></table></form>');
  return html.join('');
};


/**
 * Gets event time in 'hrs : mins' format.
 * @param {Date} eventDate Date for which time is to be calculated.
 * @return {string} Returns time in 'hrs : mins' format.
 */
function getTime(eventDate) {
  var hrs = eventDate.getHours();
  if (hrs < 10) {
    hrs = '0' + hrs;
  }
  var mins = eventDate.getMinutes();
  if (mins < 10) {
    mins = '0' + mins;
  }
  return hrs + ':' + mins;
}

/**
 * Returns the given date as format specified in locale.
 * @param {Object} date Date to be changed into locale format.
 * @return {string} Locale specific date format.
 */
function getDateInLocaleFormat(date) {
  var day = date.getDate();
  var dd = day < 10 ? '0' + day : day;
  return MESSAGES['date_format'].replace('%dd%', dd)
      .replace('%d%', day)
      .replace('%mmmm%', MESSAGES['M_' + date.getMonth()])
      .replace('%m%', date.getMonth())
      .replace('%yyyy%', date.getFullYear());
}

/**
 * Parse the specified attribute of a node.
 * @param {Object} element Node element.
 * @param {string} attrib Name of the attribute.
 * @return {string} Value of the node.
 */
function getAttributeValue(element, attrib) {
  return element && element.attributes &&
      element.attributes.getNamedItem(attrib) &&
      element.attributes.getNamedItem(attrib).value;
}

/**
 * Parse the value of a node.
 * @param {Object} element The node which needs to be parsed.
 * @return {string} Value of the node.
 */
function getNodeValue(element) {
  return element && element.firstChild && element.firstChild.nodeValue;
}

/**
 * Converts string into a date object.
 * @param {string} fullDateString A string in the UTC format
 *     YYYY-MM-DD-THH:mm:SSZ
 *     (year, month, day of month, hours, minutes, seconds)
 *     An example of this field is: "2010-06-11T14:00:00Z", which is
 *     June. 11rd 2010 14:00:00, in the timezone UTC 0.
 * @return {Date} Date object adjusted to local time.
 */
function getMatchDateObj(fullDateString) {
  var date = new Date(fullDateString.substr(0, 4),
                      fullDateString.substr(5, 2) - 1,
                      fullDateString.substr(8, 2),
                      fullDateString.substr(11, 2),
                      fullDateString.substr(14, 2),
                      fullDateString.substr(17, 2));

  // Get the local time.
  date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
  return date;
}

function getWaveContent(matchNumber) {
  var match = getMatchByMatchNumber(matchNumber);
  if (!match) {
    return;
  }
  return 'Some information to inform about adding robot to the gadget.';
}

function getMatchByMatchNumber(matchNumber) {
  var item, index;
  var length = events.length;
  for (index = 0; index < length; index++) {
    item = events[index];
    if (item.matchNumber == matchNumber) {
      return item;
    }
  }
  return null;
}

function waveThis(matchNumber, action) {
  var match = getMatchByMatchNumber(matchNumber);
  if (!match) {
    return;
  }
  var urlElement = document.getElementById('url-reference-' + matchNumber);
  var urlValue = urlElement.value;
  var index = urlValue.indexOf('&action=');
  if (index != -1) {
    // Remove the previous action.
    urlValue = urlValue.substring(0, index);
  }
  urlElement.value = urlValue + '&action=' + action;
  var formElement = document.getElementById('wave-this-' + matchNumber);
  formElement.submit();
}

function renderUI(parentId) {
  var index, html = [], item;
  var length = events.length;
  for (index = 0; index < length; index++) {
    item = events[index];
    html.push('<div class="match">' + createMatchSchedule(item) + '</div>');
  }
  document.getElementById(parentId).innerHTML = html.join('');
}

function renderUIForMatch(parentId, matchId) {
  var match = getMatchByMatchNumber(matchNumber);
  var html = '';
  if (!match) {
    html = 'No match found for the given match id.';
  } else {
    html = '<div class="match">' + createMatchSchedule(item) + '</div>';
  }
  document.getElementById(parentId).innerHTML = html.join('');
}

/**
 *
 *
 */
function getXMLHTTPObject() {
  if (window.XMLHttpRequest) {
    // code for IE7+, Firefox, Chrome, Opera, Safari
    return new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    // code for IE6, IE5
    return new ActiveXObject("Microsoft.XMLHTTP");
  }
  return null;
}

function callbackMatchList(request, responseText, opt_matchId) {
  var responseXml, events;
  if (request.readyState == 4 && request.status == 200) {
    //console.log('responseText', responseText);
    responseXml = request.responseXML;
    //console.log('responseXml', responseXml);
    events = parseWorldCupEventsData(responseXml);
    //console.log('events', events);
    if (typeof opt_matchId === 'number' || typeof opt_matchId === 'string') {
      renderUIForMatch('main-content', opt_matchId);
    } else {
      renderUI('main-content');
    }
  }
}

/**
 *
 */
function sendRequestMatchList(opt_matchId) {
  var request = getXMLHTTPObject();
  var callback = function(responseText) {
    callbackMatchList(request, responseText, opt_matchId);
  };
  request.onreadystatechange = callback;
  request.open('GET', SCHEDULE_URL, true);
  request.send(null);
}



function init(opt_matchId) {
  sendRequestMatchList(opt_matchId);
}

